package framework.remote
{
	import framework.handle;

	import mx.collections.ArrayCollection;
	import mx.collections.IList;
	import mx.rpc.AsyncToken;
	import mx.rpc.events.ResultEvent;

	public class RemoteCollection extends ArrayCollection
	{

		public function RemoteCollection(func:Function, args:Array, source:Array =
										 null)
		{
			this.args = args;
			this.func = func;
			super(source);
		}

		public var args:Array;

		public var func:Function;

		public var token:AsyncToken;

		[Bindable]
		public var totalPages:int;

		private var _currentPage:int = -1;

		private var _pageSize:int = 0;

		public var dataLoaded:Boolean;

		public function addRemoteItem(addToken:AsyncToken, item:Object = null):AsyncToken
		{
			handle(addToken, addFuncHandler);
			addToken.item = item;
			return addToken;
		}

		[Bindable]
		public function get currentPage():int
		{
			return _currentPage;
		}

		public function set currentPage(page:int):void
		{
			_currentPage = page;
			refresh();
		}

		[Bindable]
		public function get pageSize():int
		{
			return _pageSize;
		}

		public function set pageSize(s:int):void
		{
			_pageSize = s;
			totalPages = int(source.length / _pageSize);
			if ((source.length % _pageSize) != 0)
				totalPages++;
			if (filterFunction == null)
			{
				filterFunction = pagedFilterFunction;
			}
			currentPage = 0;
		}

		public function refreshRemote():AsyncToken
		{
			if (token && !dataLoaded)
			{
				return token;
			}
			dataLoaded = false;
			token = handle(func.apply(this, args), handleResult);
			return token;
		}

		public function removeRemoteItemAt(removeToken:AsyncToken, index:int):AsyncToken
		{
			handle(removeToken, removeFuncHandler);
			removeToken.index = index;
			return removeToken;
		}

		private function addFuncHandler(re:ResultEvent):void
		{
			var item:Object = re.token.item;
			if (!item)
			{
				item = re.result;
			}
			addItem(item);
		}

		private function handleResult(re:ResultEvent):void
		{
			removeAll();
			if (re.result)
				addAll(re.result as IList);
			dataLoaded = true;
		}

		private function pagedFilterFunction(obj:Object):Boolean
		{
			var i:int = source.indexOf(obj) - _pageSize * _currentPage;
			if (i >= 0 && i < _pageSize)
			{
				return true;
			}
			return false;
		}

		private function removeFuncHandler(re:ResultEvent):void
		{
			var index:int = re.token.index;
			removeItemAt(index);
		}

		public function nextPage():void
		{
			if (_currentPage < totalPages - 1)
			{
				currentPage++;
			}
		}

		public function previousPage():void
		{
			if (_currentPage != 0)
			{
				currentPage--;
			}
		}
	}
}